package com.xhtech.base.view.load

import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.animation.AnimationUtils
import com.blankj.utilcode.util.ThreadUtils
import com.xhtech.base.R
import com.xhtech.base.databinding.LayoutEmptyViewBinding
import com.xhtech.base.databinding.LayoutErrorViewBinding
import com.xhtech.base.databinding.LayoutLoadingViewBinding
import com.xhtech.base.databinding.ViewStateLayoutBinding
import com.xhtech.ui.view.load.*
import com.yxh.lib_base.base.BaseLifecycleView
import com.yxh.lib_base.ext.lazyNone
import com.yxh.lib_base.ext.view.clickNoRepeat
import com.yxh.lib_base.ext.view.gone
import com.yxh.lib_base.ext.view.visible
import com.yxh.lib_base.ext.view.visibleOrGone
import com.yxh.lib_base.ext.viewbinding.binding
import java.lang.System.currentTimeMillis

/**
 *
 * @author  XQ Yang
 * @date 5/6/2018  12:23 PM
 */
class MStateView(context: Context, attrs: AttributeSet? = null) : BaseLifecycleView(context, attrs),
    IStateView {

    override var emptyMsg: String = "這里什么也没有噢!ヾ(･ω･`｡)"
    override var tvRetryMsg: String = "重试看看"
    override var tvErrDes: String = "请检查您的网络，重新加载吧"
    override var errorMsg: String = "怎么回事,出错了!(⊙_⊙)?"
    override var onStateChanged: ((Int) -> Unit)? = null
    override var curState: Int = STATE_EMPTY
    private var bindViewId = 0 //绑定的id

    override var onRetry: (() -> Unit)? = null

    //绑定的view
    override var bindView: View? = null

    private val mBinding by binding<ViewStateLayoutBinding>()

    private val mEmptyBinding by lazyNone { mBinding.vsEmpty.binding as LayoutEmptyViewBinding }
    private val mErrorBinding by lazyNone { mBinding.vsError.binding as LayoutErrorViewBinding }
    private val mLoadingBinding by lazyNone { mBinding.vsLoading.binding as LayoutLoadingViewBinding }

    private val emptyLayout: View by lazyNone {
        mEmptyBinding.tvEmpty.text = emptyMsg
        mEmptyBinding.root
    }

    private val errorLayout: View by lazyNone {
        val view = mErrorBinding.root
        with(mErrorBinding) {
            tvError.text = errorMsg
            btnRetry.text = tvRetryMsg
        }
        view
    }

    private val loadingLayout: View by lazyNone {
        mLoadingBinding.root
    }

    private var mLastOpenTime: Long = 0 //上一次 刷新或者加载 时间

    //延时剩余时间
    private fun getRemainingTime(): Long {
        return getRemainingTime(300)
    }

    private fun getRemainingTime(mTime: Int): Long {
        val passTime = currentTimeMillis() - mLastOpenTime
        val delayed = Math.min(Math.max(0, mTime - passTime.toInt()), mTime) //保证加载动画有300毫秒的时间
        val more = delayed shr 16 //动画剩余延时
        val delay = delayed shl 16 shr 16 //用户指定延时
        return delayed.toLong()
    }


    override fun showItemCount(count: Int) {
        if (count > 0) showSuccess() else showEmpty(emptyMsg)
    }

    override fun showSuccess() {
        showSuccess(getRemainingTime())
    }

    fun showSuccess(timeLong: Long) {
        if (curState == STATE_SUCCESS) return
        ThreadUtils.runOnUiThreadDelayed({
            //            hideAll()
            //            bindView?.visibility = View.VISIBLE
            hideAllFilter(STATE_SUCCESS)
            curState = STATE_SUCCESS
            onStateChanged?.invoke(STATE_SUCCESS)
        }, timeLong)
    }

    override fun showError(msg: String?) {
        ThreadUtils.runOnUiThreadDelayed({
            //            hideAll()
            hideAllFilter(STATE_ERROR)
            with(mErrorBinding){
                msg?.let { tvError.text = it }
                tvErrDes.visibleOrGone(!this@MStateView.tvErrDes.isNullOrEmpty())?.text = this@MStateView.tvErrDes

                btnRetry.text = tvRetryMsg
                btnRetry.clickNoRepeat {
                    onRetry?.invoke()
                }

            }
            curState = STATE_ERROR
            onStateChanged?.invoke(STATE_ERROR)
        }, getRemainingTime())
    }

    override fun showEmpty(msg: String?) {
        if (curState == STATE_EMPTY) {
            msg?.let {
                emptyLayout.visible()
                mEmptyBinding.tvEmpty.text = it
            }
        } else {
            ThreadUtils.runOnUiThreadDelayed({
                hideAllFilter(STATE_EMPTY)
                msg?.let {
                    mEmptyBinding.tvEmpty.text = it
                }
                //                emptyLayout.visibility = View.VISIBLE
                curState = STATE_EMPTY
                onStateChanged?.invoke(STATE_EMPTY)
            }, getRemainingTime())
        }
    }

    override fun showEmptyBtn(msg: String?) {
        ThreadUtils.runOnUiThreadDelayed({
            //            hideAll()
            hideAllFilter(STATE_EMPTY_ERROR)
            msg?.let {
                mErrorBinding.tvError.text = it
            }

            mErrorBinding.tvErrDes.gone()
            mErrorBinding.btnRetry.text = tvRetryMsg
            mErrorBinding.btnRetry.clickNoRepeat {
                onRetry?.invoke()
            }
            curState = STATE_EMPTY_ERROR
            onStateChanged?.invoke(STATE_EMPTY_ERROR)
        }, getRemainingTime())
    }

    override fun showLoading() {
        if (curState == STATE_LOADING) return

        hideAllFilter(STATE_LOADING)
        curState = STATE_LOADING
        onStateChanged?.invoke(STATE_LOADING)
        //loading加载 时间
        mLastOpenTime = currentTimeMillis()
    }

    override fun <T, DATA : IListBean<T>> getState(bean: IStateBean<T, DATA>?): Int {
        return if (bean?.isOk() == true) {
            if (bean.result?.list == null || bean.result!!.list.isEmpty()) STATE_EMPTY else STATE_SUCCESS
        } else {
            STATE_ERROR
        }
    }

    override fun <T, DATA : IListBean<T>> setData(bean: IStateBean<T, DATA>?) {
        when (getState(bean)) {
            STATE_SUCCESS -> showSuccess()
            STATE_EMPTY -> showEmpty()
            STATE_ERROR -> showError()
            STATE_LOADING -> showLoading()
        }
    }


    override fun setBackgroundColor(color: Int) {
        super.setBackgroundColor(color)
        mBinding.flRoot.setBackgroundColor(color)
    }

    private fun hideAll() {
        if (bindView == null) {
            bindView = findViewById(bindViewId)
        }
        bindView?.visibility = View.GONE
        mBinding.vsEmpty.viewStub?.visibility = View.GONE
        errorLayout.visibility = View.GONE
        loadingLayout.visibility = View.GONE
    }

    private fun hideAllFilter(@ViewState toState: Int) {
        if (bindView == null) {
            bindView = findViewById(bindViewId)
        }

        when (toState) {
            STATE_SUCCESS -> {
                bindView?.run {
                    if (!isShown) {
                        startAnimation(
                            AnimationUtils.loadAnimation(
                                context,
                                android.R.anim.fade_in
                            )
                        )
                    }
                    visible()
                }
                mLoadingBinding.aviLoading.hide()
                loadingLayout.gone()
                emptyLayout.gone()
                errorLayout.gone()

            }
            STATE_EMPTY -> {
                bindView?.invalidate()
                emptyLayout.visible()
                errorLayout.gone()
                mLoadingBinding.aviLoading.hide()
                loadingLayout.gone()
            }
            STATE_ERROR -> {
                mLoadingBinding.aviLoading.hide()
                loadingLayout.gone()
                bindView?.gone()
                emptyLayout.gone()
                errorLayout.visible()
            }
            STATE_EMPTY_ERROR -> {
                bindView?.gone()
                emptyLayout.gone()
                errorLayout.visible()
                mLoadingBinding.aviLoading.hide()
                loadingLayout.gone()
            }
            STATE_LOADING -> {
                if (curState != toState) {
                    loadingLayout.run {
                        startAnimation(
                            AnimationUtils.loadAnimation(
                                context,
                                android.R.anim.fade_in
                            )
                        )
                        visible()
                    }
                    mLoadingBinding.aviLoading.smoothToShow()
                    bindView?.run {
                        if (isShown) {
                            startAnimation(
                                AnimationUtils.loadAnimation(
                                    context,
                                    android.R.anim.fade_out
                                )
                            )
                        }
                        gone()
                    }
                    emptyLayout.gone()
                    errorLayout.gone()
                }
            }
        }
    }


    override fun onFinishInflate() {
        super.onFinishInflate()
        mLastOpenTime = currentTimeMillis()
        when (curState) {
            STATE_SUCCESS -> showSuccess()
            STATE_EMPTY -> showEmpty()
            STATE_ERROR -> showError()
            STATE_LOADING -> showLoading()
            STATE_EMPTY_ERROR -> showEmptyBtn()
        }
    }

    init {
        mLastOpenTime = currentTimeMillis()
        val attributes = context.obtainStyledAttributes(attrs, R.styleable.MStateView)
        bindViewId = attributes.getResourceId(R.styleable.MStateView_bindId, -1)
        curState = attributes.getInt(R.styleable.MStateView_startState, STATE_LOADING)
        attributes.recycle()
    }

}